#include "center.h"

namespace cores
{
    namespace topics
    {
        /**
         * @brief 全局变量，单例
         * 
         */
        TopicsCenter TopicsCenter::globalInstance;

        Topic::Topic(const std::string& topic) : _topic(topic)
        {}

        Topic::~Topic()
        {
            std::unique_lock<std::mutex> lock(_mutex);
            _subscribers.clear();
        }

        void Topic::append(Subscriber * subscriber)
        {
            std::unique_lock<std::mutex> lock(_mutex);
            for (auto &sub : _subscribers)
            {
                if (sub == subscriber)
                    return;
            }

            _subscribers.push_back(subscriber);
        }

        void Topic::remove(Subscriber * subscriber)
        {
            std::unique_lock<std::mutex> lock(_mutex);
            for (auto iter = _subscribers.begin(); iter != _subscribers.end(); ++iter)
            {
                if (*iter == subscriber)
                {
                    _subscribers.erase(iter);
                    return;
                }
            }
        }

        TopicsCenter::TopicsCenter()
        {}

        TopicsCenter::~TopicsCenter()
        {
            for (auto iter : _mapTopics)
            {
                iter.second.reset();
            }
            _mapTopics.clear();
        }

        TopicsCenter* TopicsCenter::Instance()
        {
            return &TopicsCenter::globalInstance;
        }

        void TopicsCenter::subscribe(const std::string& topic, Subscriber * subscriber)
        {
            if (_mapTopics.count(topic) == 0 || _mapTopics[topic].get() == nullptr)
            {
                _mapTopics[topic] = std::make_shared<Topic>(topic);
            }

            _mapTopics[topic]->append(subscriber);
        }

        void TopicsCenter::unsubscribe(const std::string& topic, Subscriber * subscriber)
        {
            if (_mapTopics.count(topic) == 0 || _mapTopics[topic].get() == nullptr)
                return;

            _mapTopics[topic]->remove(subscriber);
        }
    }
}